﻿using System;
using System.Xml.Serialization;

namespace WhiteFlow.DevTrackingTool.UI.Models
{
    [Serializable]
    public class TaskExecution : WorksheetItem, ICloneable
    {
        #region Private Fields

        private TrackingDay owner;
        
        private string location;
        
        private TaskModes taskMode;
        
        private TaskTypes taskType;
        
        private string taskTitle;
        
        private string taskDescription;
        
        private string notes;
        
        private TimeSpan startTime;
        
        private TimeSpan endTime;
        
        //private ExtendedBoolean isReportDone;
        
        //private ExtendedBoolean isExpenseReportCompiled;
        
        private TimeSpan totalTime;
        
        private double totalTimeDecimal;
        
        private string customer;
        
        private string project;
        
        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="TaskExecution"/> class.
        /// </summary>
        private TaskExecution() { }

        /// <summary>
        /// Initializes a new instance of the <see cref="TaskExecution"/> class.
        /// </summary>
        public TaskExecution(TrackingDay owner)
        {
            SetOwner(owner);
            
            // Raise the OnPropertyChanged event on one property, just to notify
            // that this object is in a dirty state.
            OnPropertyChanged("Location");
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the location in which the task is executed.
        /// </summary>
        public string Location
        {
            get { return location; }
            set
            {
                location = value;
                OnPropertyChanged("Location");
                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the customer for which the task has been (or is being) performed.
        /// </summary>
        public string Customer
        {
            get { return customer; }
            set
            {
                customer = value;
                OnPropertyChanged("Customer");
                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the project on which the task is focused.
        /// </summary>
        public string Project
        {
            get { return project; }
            set
            {
                project = value;
                OnPropertyChanged("Project");
                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the execution mode of the task (generally if it's executed on-site or remotely.
        /// </summary>
        public TaskModes TaskMode
        {
            get { return taskMode; }
            set
            {
                taskMode = value;
                OnPropertyChanged("TaskMode");
                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the type of the task.
        /// </summary>
        public TaskTypes TaskType
        {
            get { return taskType; }
            set
            {
                taskType = value;
                OnPropertyChanged("TaskType");
                OnWorksheetItemChanged();
            }
        }
        
        /// <summary>
        /// Gets or sets the title of the task.
        /// </summary>
        [XmlElement(ElementName = "TaskTitle", IsNullable = false)]
        public string TaskTitle
        {
            get { return taskTitle; }
            set
            {
                taskTitle = value;
                OnPropertyChanged("TaskTitle");

                if (owner != null)
                {
                    owner.UpdateTasksSummary();
                }

                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the description of the task.
        /// </summary>
        [XmlElement(ElementName = "TaskDescription", IsNullable = true)]
        public string TaskDescription
        {
            get { return taskDescription; }
            set
            {
                taskDescription = value;
                OnPropertyChanged("TaskDescription");
                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the notes for the task.
        /// </summary>
        [XmlElement(ElementName = "Notes", IsNullable = true)]
        public string Notes
        {
            get { return notes; }
            set
            {
                notes = value;
                OnPropertyChanged("Notes");
                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the start time for the task.
        /// </summary>
        /// <value>
        /// The start time for the task.
        /// </value>
        [XmlIgnore]
        public TimeSpan StartTime
        {
            get { return startTime; }
            set
            {
                startTime = value;
                OnPropertyChanged("StartTime");
                
                UpdateTaskTotalTime();
                
                if (owner != null)
                {
                    owner.UpdateAllTasksTotalTimes();
                    owner.UpdateTasksSummary();
                }

                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the start time for the task, expressed in ticks.
        /// </summary>
        /// <value>
        /// The start time for the task, expressed in ticks.
        /// </value>
        [XmlElement(ElementName = "StartTime", IsNullable = false)]
        public long StartTimeTicks
        {
            get { return StartTime.Ticks; }
            set { StartTime = new TimeSpan(value); }
        }

        /// <summary>
        /// Gets or sets the end time for the task.
        /// </summary>
        /// <value>
        /// The end time for the task.
        /// </value>
        [XmlIgnore]
        public TimeSpan EndTime
        {
            get { return endTime; }
            set
            {
                endTime = value;
                OnPropertyChanged("EndTime");

                UpdateTaskTotalTime();

                if (owner != null)
                {
                    owner.UpdateAllTasksTotalTimes();
                    owner.UpdateTasksSummary();
                }

                OnWorksheetItemChanged();
            }
        }

        /// <summary>
        /// Gets or sets the end time for the task, expressed in ticks.
        /// </summary>
        /// <value>
        /// The end time for the task, expressed in ticks.
        /// </value>
        [XmlElement(ElementName = "EndTime", IsNullable = false)]
        public long EndTimeTicks
        {
            get { return EndTime.Ticks; }
            set { EndTime = new TimeSpan(value); }
        }

        [XmlIgnore]
        public TimeSpan TotalTime
        {
            get { return totalTime; }
            set
            {
                totalTime = value;
                OnPropertyChanged("TotalTime");
                OnWorksheetItemChanged();

                TotalTimeDecimal = totalTime.TotalHours;
            }
        }

        [XmlIgnore]
        public double TotalTimeDecimal
        {
            get { return totalTimeDecimal; }
            set
            {
                totalTimeDecimal = Math.Round(value, 2, MidpointRounding.AwayFromZero);
                OnPropertyChanged("TotalTimeDecimal");
                OnWorksheetItemChanged();
            }
        }

        //public ExtendedBoolean IsReportDone
        //{
        //    get { return isReportDone; }
        //    set
        //    {
        //        isReportDone = value;
        //        OnPropertyChanged("IsReportDone");
        //        OnWorksheetItemChanged();
        //    }
        //}

        //public ExtendedBoolean IsExpenseReportCompiled
        //{
        //    get { return isExpenseReportCompiled; }
        //    set
        //    {
        //        isExpenseReportCompiled = value;
        //        OnPropertyChanged("IsExpenseReportCompiled");
        //        OnWorksheetItemChanged();
        //    }
        //}

        #endregion

        #region Private Methods

        private void UpdateTaskTotalTime()
        {
            TimeSpan diff = new TimeSpan(0, 0, 0);

            if (EndTime.CompareTo(StartTime) >= 0)
                diff = EndTime.Subtract(StartTime);

            TotalTime = diff;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Sets the owner of the current task.
        /// </summary>
        /// <param name="owner">The owner.</param>
        public void SetOwner(TrackingDay owner)
        {
            if (owner != null)
            {
                this.owner = owner;

                owner.UpdateAllTasksTotalTimes();
                owner.UpdateTasksSummary();
            }
        }

        #endregion

        #region ICloneable Members

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public object Clone()
        {
            return new TaskExecution(owner)
            {
                Customer = Customer,
                EndTime = EndTime,
                Location = Location,
                Notes = Notes,
                Project = Project,
                StartTime = StartTime,
                TaskDescription = TaskDescription,
                TaskMode = TaskMode,
                TaskTitle = TaskTitle,
                TaskType = TaskType,
                TotalTime = TotalTime,
                TotalTimeDecimal = TotalTimeDecimal
            };
        }
        
        #endregion
    }
}